using System;
using System.IO;
using System.Net;
using System.Web;
using System.Text;

namespace FPSEPublish
{
    /// <summary>
    /// Summary description for FPSEPublish.
    /// </summary>
    public class FPSEPublish
    {
        public FPSEPublish()
        {
        }

        public void UrlToWebUrl(string uri, out string webUrl, out string fileUrl)
        {
            Uri myUri = new Uri(uri);

            string postBody = String.Format("method=url+to+web+url&url={0}&flags=0", myUri.AbsolutePath);
            string response = SendRequest(myUri.GetLeftPart(UriPartial.Authority) + "/_vti_bin/shtml.dll/_vti_rpc", postBody);

            webUrl = GetReturnValue(ref response, "webUrl");
            fileUrl = GetReturnValue(ref response, "fileUrl");
        }

        public void PutDocument(string uri, string fileName, string metaInfo)
        {
            //Console.WriteLine(uri + " / " + fileName + " /" + metaInfo + "\n");
            try
            {
                Uri myUri = new Uri(uri);
                string webUrl, fileUrl;
                UrlToWebUrl(uri, out webUrl, out fileUrl);

                if (null == metaInfo)
                    metaInfo = "";

                if (!File.Exists(fileName))
                    throw new Exception("Could not find file " + fileName);

                string postBody = String.Format(
                    "method=put+document&service_name=&document=[document_name={0};meta_info=[{1}]]&put_option=overwrite&comment=&keep_checked_out=false\n",
                    HttpUtility.UrlEncode(fileUrl),
                    metaInfo);

                ASCIIEncoding encoding = new ASCIIEncoding();
                MemoryStream stream = new MemoryStream();
                stream.Write(encoding.GetBytes(postBody), 0, postBody.Length);

                FileStream fs = File.OpenRead(fileName);
                byte[] b = new byte[4096];
                while (fs.Read(b, 0, b.Length) > 0)
                {
                    stream.Write(b, 0, b.Length);
                }
                fs.Close();

                SendRequest(myUri.GetLeftPart(UriPartial.Authority) + webUrl + "/_vti_bin/_vti_aut/author.dll", stream.GetBuffer(), stream.Length);
                stream.Close();
            }
            catch(Exception ex)
            {
                Console.WriteLine(ex.Message);
            }
        }

        public void CheckinDocument(string uri)
        {
            Uri myUri = new Uri(uri);
            string webUrl, fileUrl;
            UrlToWebUrl(uri, out webUrl, out fileUrl);

            string postBody = String.Format("method=checkin+document&service_name=&document_name={0}&comment=&keep_checked_out=false", fileUrl);
            SendRequest(myUri.GetLeftPart(UriPartial.Authority) + webUrl + "/_vti_bin/_vti_aut/author.dll", postBody);
        }

        public void SetDocsMetaInfo(string uri, string metaInfo)
        {
            Uri myUri = new Uri(uri);
            string webUrl, fileUrl;
            UrlToWebUrl(uri, out webUrl, out fileUrl);

            string postBody = String.Format(
                "method=set+document+meta-info&service_name=&document_name={0}&meta_info=[{1}]",
                fileUrl,
                metaInfo);
            SendRequest(myUri.GetLeftPart(UriPartial.Authority) + webUrl + "/_vti_bin/_vti_aut/author.dll", postBody);
        }

        private string SendRequest(string uri, byte[] postBody, long postLength)
        {
            string responseText = null;

            try
            {
                WebRequest request = WebRequest.Create(uri);
                request.Method = "POST";
                request.ContentType = "application/x-www-form-urlencoded";
                request.Headers.Add("X-Vermeer-Content-Type", "application/x-www-form-urlencoded");
                request.Credentials = CredentialCache.DefaultCredentials;
                Stream newStream = request.GetRequestStream();

                int offset = 0;
                while (postLength > 0)
                {
                    if (postLength > 4096)
                    {
                        newStream.Write(postBody, offset, 4096);
                        postLength -= 4096;
                        offset += 4096;
                    }
                    else
                    {
                        newStream.Write(postBody, offset, Convert.ToInt32(postLength));
                        break;
                    }
                }

                newStream.Close();

                HttpWebResponse response = (HttpWebResponse)request.GetResponse();
                Stream receiveStream = response.GetResponseStream();
                StreamReader readStream = new StreamReader(receiveStream, Encoding.UTF8);

                responseText = readStream.ReadToEnd();

                response.Close();
                readStream.Close();
            }
            catch (Exception e)
            {
                Console.WriteLine("ERROR: {0}", e.Message);
            }

            return responseText;
        }

        private string SendRequest(string uri, string postBody)
        {
            ASCIIEncoding encoding = new ASCIIEncoding();
            return SendRequest(uri, encoding.GetBytes(postBody), postBody.Length);
        }

        private string GetReturnValue(ref string response, string key)
        {
            int start = response.IndexOf(key + "=");
            if (-1 == start)
                return null;
            else
                start += key.Length + 1;

            int end = response.IndexOf("\n", start);
            return response.Substring(start, end - start);
        }

    }
}
